/// klist : adapted from klist from source_pw/module_pwdft
/// deals with k point sampling

#include "source_base/global_function.h"
#include "source_base/matrix3.h"
#include "source_base/memory.h"
#include "source_base/vector3.h"

#include <fstream>
#include <iostream>

namespace Test_Deepks
{
class K_Vectors
{
  public:
    ModuleBase::Vector3<double>* kvec_c;             // Cartesian coordinates of k points
    std::vector<ModuleBase::Vector3<double>> kvec_d; // Direct coordinates of k points

    double* wk; // wk, weight of k points

    int* isk; // distinguish spin up and down k points

    int nkstot; // total number of k points

    int nmp[3]; // Number of Monhorst-Pack

    K_Vectors();
    ~K_Vectors();

    void set(const std::string& k_file_name,
             const int& nspin,
             const ModuleBase::Matrix3& reciprocal_vec,
             const ModuleBase::Matrix3& latvec,
             bool& GAMMA_ONLY_LOCAL,
             std::ofstream& ofs_running,
             std::ofstream& ofs_warning);

  private:
    int nspin;
    bool kc_done;
    bool kd_done;
    double koffset[3];   // used only in automatic k-points.
    std::string k_kword; // LiuXh add 20180619
    int k_nkstot;        // LiuXh add 20180619

    // step 1 : generate kpoints
    bool read_kpoints(const std::string& fn,
                      bool& GAMMA_ONLY_LOCAL,
                      std::ofstream& ofs_warning,
                      std::ofstream& ofs_running);
    void Monkhorst_Pack(const int* nmp_in, const double* koffset_in, const int tipo);
    double Monkhorst_Pack_formula(const int& k_type, const double& offset, const int& n, const int& dim);

    // step 2 : set both kvec and kved; normalize weight
    void set_both_kvec(const ModuleBase::Matrix3& G, const ModuleBase::Matrix3& Rm, std::ofstream& ofs_running);
    void renew(const int& kpoint_number);
    void normalize_wk(const int& degspin);

    // step 3 : *2 or *4 kpoints.
    // *2 for LSDA
    // *4 for non-collinear
    void set_kup_and_kdw(std::ofstream& ofs_running);

    // step 4
    // print k lists.
    void print_klists(std::ofstream& fn_running);
};
} // namespace Test_Deepks
